--# Main
-- Gundam
function setup()
    displayMode(FULLSCREEN)
    long_lan = Gundam(vec2(400, 240), Animation({"gundam:long_lan_feet2", "gundam:long_lan_feet", "gundam:long_lan_feet1"}), Animation({"gundam:long_lan1", "gundam:long_lan"}), vec2(0, 0))
    joystick = Joystick()
end
function draw()
    background(0)
    
    if joystick.L_vec2 ~= vec2(0, 0) then
        long_lan.angle = vec2(0, 1):angleBetween(joystick.L_vec2)
        long_lan.velocity = joystick.L_vec2:normalize() * long_lan.speed
        long_lan.state = moving
    else
        long_lan.velocity = vec2(0, 0)
        long_lan.state = no_action
    end
    
    if joystick.R_vec2 ~= vec2(0, 0) then
        long_lan.weapon.angle = vec2(0, 1):angleBetween(joystick.R_vec2)
    end
    
    long_lan:draw()
    fill(0, 255, 0)
    stroke(0, 255, 0)
    strokeWidth(1)
    rect(10 * WIDTH / 800, 460 * HEIGHT / 480, (long_lan.hp / long_lan.fullhp) * 780 * WIDTH / 800, 10 * HEIGHT / 480)
    joystick:draw()
end
function touched(touch)
    joystick:touched(touch)
end

--# Weapon
Weapon = class()
function Weapon:init(offpos, anime)
    -- user variable
    self.offset_position = offpos
    self.animation = anime
    self.angle = 0 -- rad
    self.bullets = {}
    -- class variable
    self.render = mesh()
    local width, height = spriteSize(self.animation.frames[self.animation.index])
    self.rectangleID = self.render:addRect(
    self.offset_position.x * WIDTH / 800, self.offset_position.y * HEIGHT / 480, width * WIDTH / 800,
    height * HEIGHT / 480, 0) -- define the offset drawing area
    self.render:setRectTex(self.rectangleID, 0.0, 0.0, 1.0, 1.0) -- define the texture area
    self.render.texture = self.animation.frames[self.animation.index] -- load the texture
end


--# Animation
Animation = class()
function Animation:init(frames)
    self.frames = frames
    self.index = 1
    self.frame = 0
    self.speed = 5
end
function Animation:playing()
    self.frame = self.frame + 1
    if self.frame == self.speed then
        if self.index < #self.frames then
            self.index = self.index + 1
        else
            self.index = 1
        end
        self.frame = 0
    end
end
--# Bullet
Bullet = class()
function Bullet:init(pos, angle, img)
    -- user variable
    self.position = pos
    self.angle = angle -- rad
    self.speed = 7 * HEIGHT / 480
    self.velocity = vec2(0, 1):rotate(angle) * self.speed
    self.damage = 10
    -- class variable
    self.render = mesh()
    self.width, self.height = spriteSize(img)
    self.rectangleID = self.render:addRect(
    self.position.x * WIDTH / 800, self.position.y * HEIGHT / 480, self.width * WIDTH / 800,
    self.height * HEIGHT / 480, self.angle) -- define the drawing area
    self.render:setRectTex(self.rectangleID, 0.0, 0.0, 1.0, 1.0) -- define the texture area
    self.render.texture = img -- load the texture
end
function Bullet:draw()
    self.position = self.position + self.velocity
    self.render:setRect(self.rectangleID,
    self.position.x * WIDTH / 800, self.position.y * HEIGHT / 480,
    self.width * WIDTH / 800, self.height * HEIGHT / 480, self.angle) -- adjust the bullet's drawing area
    self.render:draw()
end
--# Constant_Variable_List
-- const
pi = 3.1415926
-- variable
volume = 1.0
-- action type
no_action = 1
moving = 2


--# Gundam
Gundam = class()
function Gundam:init(pos, body, head, head_offset)
    -- user variable
    self.position = pos
    self.angle = 0 -- rad
    self.animation = body
    self.weapon = Weapon(head_offset, head)
    self.hp = 100
    self.fullhp = 100
    self.ep = 50
    self.fullep = 50
    self.def = 0
    self.speed = 2 * HEIGHT / 480 -- pixel
    self.velocity = vec2(0, 0)
    self.state = no_action
    -- class variable
    self.render = mesh()
    local width, height = spriteSize(self.animation.frames[self.animation.index])
    self.rectangleID = self.render:addRect(
    self.position.x * WIDTH / 800, self.position.y * HEIGHT / 480, width * WIDTH / 800,
    height * HEIGHT / 480, 0) -- define the drawing area
    self.render:setRectTex(self.rectangleID, 0.0, 0.0, 1.0, 1.0) -- define the texture area
    self.render.texture = self.animation.frames[self.animation.index] -- load the texture
end
function Gundam:draw()
    self.position = self.position + self.velocity
    if self.state == moving then
        self.animation:playing()
    else
        self.animation.index = 1
    end
    self.weapon.animation:playing()
    if self.weapon.animation.frame == 0 and self.weapon.animation.index == 1 then
        table.insert(self.weapon.bullets, Bullet(self.position + vec2(27, 13):rotate(self.weapon.angle),
        self.weapon.angle, "gundam:bullet"))
        table.insert(self.weapon.bullets, Bullet(self.position + vec2(-27, 13):rotate(self.weapon.angle),
        self.weapon.angle, "gundam:bullet"))
    end -- shoot
    for index, bullet in ipairs(self.weapon.bullets) do
        bullet:draw()
        if bullet.position.x > 850 or bullet.position.x < -50 or
        bullet.position.y > 500 or bullet.position.y < -20 then
            table.remove(self.weapon.bullets, index)
        end
    end -- check the bullets' positions, if one is over the screen, then remove it
    local width, height = spriteSize(self.animation.frames[self.animation.index])
    local weapon_w, weapon_h = spriteSize(self.weapon.animation.frames[self.weapon.animation.index])
    self.render:setRect(self.rectangleID,
    self.position.x * WIDTH / 800, self.position.y * HEIGHT / 480,
    width * WIDTH / 800, height * HEIGHT / 480, self.angle) -- adjust the gundam's drawing area
    self.render.texture = self.animation.frames[self.animation.index] -- change the gundam's texture
    self.weapon.render:setRect(self.weapon.rectangleID,
    (self.position.x + self.weapon.offset_position.x) * WIDTH / 800,
    (self.position.y + self.weapon.offset_position.y) * HEIGHT / 480,
    weapon_w * WIDTH / 800, weapon_h * HEIGHT / 480, self.weapon.angle) -- adjust the weapon's drawing area
    self.weapon.render.texture = self.weapon.animation.frames[self.weapon.animation.index]
    -- change the weapon's drawing area
    -- draw
    self.render:draw()
    self.weapon.render:draw()
end



--# Joystick
-- Joystick
Joystick = class()
function Joystick:init() -- 实例化
    self.L_x = 100 * WIDTH / 800 -- L摇杆横坐标
    self.L_y = 85 * HEIGHT / 480 -- L摇杆纵坐标
    self.L_size = 140 * HEIGHT / 480 -- L摇杆大小(直径)
    self.L_vec2 = vec2(0, 0) -- L摇杆位置数据
    self.L_touchID = nil
    self.R_x = 700 * WIDTH / 800 -- R摇杆横坐标
    self.R_y = 85 * HEIGHT / 480 -- R摇杆纵坐标
    self.R_size = 140 * HEIGHT / 480 -- R摇杆大小(直径)
    self.R_vec2 = vec2(0, 0) -- R摇杆位置数据
    self.R_touchID = nil
    self.touches = {}
end
function Joystick:draw()
    pushStyle()
    ellipseMode(CENTER)
    fill(255, 20)
    stroke(255, 200)
    strokeWidth(4 * HEIGHT / 480)
    ellipse(self.L_x, self.L_y, self.L_size)
    ellipse(self.R_x, self.R_y, self.R_size)
    for touchID, touch in pairs(self.touches) do
        local L_module = math.sqrt((touch.x - self.L_x) ^ 2 + (touch.y - self.L_y) ^ 2)
        local R_module = math.sqrt((touch.x - self.R_x) ^ 2 + (touch.y - self.R_y) ^ 2)
        if L_module <= self.L_size / 2 then
            self.L_vec2 = vec2(touch.x - self.L_x, touch.y - self.L_y)
            self.L_touchID = touchID -- record the left touchID
            fill(255, 50)
            stroke(255)
            strokeWidth(2 * HEIGHT / 480)
            ellipse(self.L_x + self.L_vec2.x, self.L_y + self.L_vec2.y, self.L_size / 2)
        elseif touch.state == MOVING and self.L_touchID == touchID then -- check the touchID
            local L_vector = vec2(touch.x - self.L_x, touch.y - self.L_y)
            self.L_vec2 = self.L_size / 2 * L_vector:normalize()
            fill(255, 50)
            stroke(255)
            strokeWidth(2 * HEIGHT / 480)
            ellipse(self.L_x + self.L_vec2.x, self.L_y + self.L_vec2.y, self.L_size / 2)
        else
            if R_module <= self.R_size / 2 then
                self.R_vec2 = vec2(touch.x - self.R_x, touch.y - self.R_y)
                self.R_touchID = touchID -- record the right touchID
                fill(255, 50)
                stroke(255)
                strokeWidth(2 * HEIGHT / 480)
                ellipse(self.R_x + self.R_vec2.x, self.R_y + self.R_vec2.y, self.R_size / 2)
            elseif touch.state == MOVING and self.R_touchID == touchID then -- check the touchID
                local R_vector = vec2(touch.x - self.R_x, touch.y - self.R_y)
                self.R_vec2 = self.R_size / 2 * R_vector:normalize()
                fill(255, 50)
                stroke(255)
                strokeWidth(2 * HEIGHT / 480)
                ellipse(self.R_x + self.R_vec2.x, self.R_y + self.R_vec2.y, self.R_size / 2)
            end
        end
    end
    popStyle()
end
function Joystick:touched(touch)
    if touch.state == ENDED then
        self.touches[touch.id] = nil
        if self.L_touchID == touch.id then
            self.L_vec2 = vec2(0, 0)
        end
        if self.R_touchID == touch.id then
            self.R_vec2 = vec2(0, 0)
        end
    else
        self.touches[touch.id] = touch
    end
    
end